import imgui, * as im from "./imgui";
import * as imgui_imp from "./imgui_impl";
declare global {
    interface IimguiWindow {
        readonly key: string;
        isShow: boolean;
        onStartUp?(): void;
        loop(time?: number): void;
    }
}
export class ImguiMgr {
    private _isDestroy: boolean;
    private _windowMap: { [key: string]: IimguiWindow } = {};
    private _isStartUped: boolean;
    /**0~60 */
    private _fps: number = 60;
    private _interval: number = 0;
    private _isStopLoop: boolean = true;
    /**
     * 设置绘制频率
     * @param fps 
     */
    public setFPS(fps: number) {
        fps = !fps || fps > 60 ? 60 : fps;
        this._fps = fps;
        this._interval = 1000 / fps;
    }
    // private _imguiTimer: Laya.Timer = new Laya.Timer();
    public registWindow(imWindow: IimguiWindow) {
        if (!imWindow || !imWindow.key) {
            console.error("窗口实例或窗口key为空");
            return;
        }
        const windowMap = this._windowMap;
        if (windowMap[imWindow.key]) {
            console.error(`重复注册`);
        } else {
            windowMap[imWindow.key] = imWindow;
        }
    }
    showWindow(key: string) {
        this.setWindowVisible(key, true);
    }
    hideWindow(key: string) {
        this.setWindowVisible(key, false);
    }
    hideAll() {
        this.setAllWindowVisible(false);
    }
    showAll() {
        this.setAllWindowVisible(true);
    }
    setWindowVisible(key: string, visible: boolean) {
        const imWindow = this._windowMap[key];
        if (imWindow) {
            imWindow.isShow = visible;
        }
    }
    setAllWindowVisible(visible: boolean) {
        const windowMap = this._windowMap;
        for (let key in windowMap) {
            windowMap[key].isShow = visible;
        }
    }
    startUp(canvas?: HTMLCanvasElement, inserBeforeEleId?: string) {
        if (this._isStartUped) {
            this._isStopLoop && this.startLoop();
            return;
        }
        imgui().then(async () => {
            im.IMGUI_CHECKVERSION();
            im.CreateContext();

            const io: im.ImGuiIO = im.GetIO();
            // io.ConfigFlags |= ImGui.ConfigFlags.NavEnableKeyboard;  // Enable Keyboard Controls
            // io.Fonts.AddFontDefault();
            // io.Fonts.Fonts[0].Glyphs.push(io.Fonts.Fonts[0].FindGlyph(io.Fonts.GetGlyphRangesChineseFull()));
            // io.FontDefault.native. = 18;
            // console.log(io.Fonts.Fonts)
            // io.Fonts.AddFontFromMemoryTTF()
            // const font = await this.addFontFromFileTTF("../imgui/misc/fonts/Cousine-Regular.ttf", 15.0);
            // const font = await this.addFontFromFileTTF("../imgui/misc/fonts/DroidSans.ttf", 16.0);
            // const font = await this.addFontFromFileTTF("fonts/Cousine-Regular.ttf", 19.0, null);
            // const font = await this.addFontFromFileTTF("fonts/simhei.ttf", 16, null);
            // const font = await this.addFontFromFileTTF("fonts/FZZYJW.ttf", 16, null, io.Fonts.GetGlyphRangesChineseFull());
            // const font = await this.addFontFromFileTTF("fonts/DroidSans.ttf", 19.0, null, io.Fonts.GetGlyphRangesChineseFull());
            const font2 = await this.addFontFromFileTTF("fonts/DroidSansFallback.ttf", 19.0, null, io.Fonts.GetGlyphRangesChineseFull());
            io.FontDefault = font2;

            // im.IM_ASSERT(font !== null);
            im.IM_ASSERT(font2 !== null);
            // testFont = font;
            // Setup style
            im.StyleColorsDark();
            let useCreateCanvas: boolean = false;
            if (!canvas) {
                useCreateCanvas = true;
                const output: HTMLElement = document.getElementById("output") || document.body;
                canvas = document.createElement("canvas");
                const inserBeforeEle = document.getElementById(inserBeforeEleId);
                output.insertBefore(canvas, inserBeforeEle ? inserBeforeEle : output.children[0]);
                canvas.tabIndex = 1;
                canvas.style.position = "absolute";
                canvas.style.left = "0px";
                canvas.style.right = "0px";
                canvas.style.top = "0px";
                canvas.style.bottom = "0px";
                canvas.style.width = "100%";
                canvas.style.height = "100%";
                canvas.style.imeMode = "auto";
            }
            let context_options: WebGLContextAttributes = {
                alpha: true, //this enables an alpha channnel in rendering buffer
            };
            imgui_imp.Init(canvas, context_options);
            if (useCreateCanvas) {
                const gl = imgui_imp.gl;
                gl.clearColor(0, 0, 0, 0);
                gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
                gl.enable(gl.BLEND);
                gl.clear(gl.COLOR_BUFFER_BIT);
            }

            let window: IimguiWindow;
            for (let key in this._windowMap) {
                window = this._windowMap[key];
                window && window.onStartUp && window.onStartUp();
            }
            this.setFPS(this._fps);
            this.startLoop();
            this._isStartUped = true;
        });
    }

    startLoop() {
        let then = Date.now();
        const interval = this._interval;

        const tick = () => {
            if (this._isStopLoop) return;
            requestAnimationFrame(tick);
            const now = Date.now();
            let delta = now - then;
            if (delta > interval) {
                then = now - (delta % interval);
                this.render(delta)
            }
        }
        this._isStopLoop = false;
        tick();
    }
    stopLoop() {
        this._isStopLoop = true;
    }
    render(delta: number) {
        imgui_imp.NewFrame(delta);
        im.NewFrame();
        const windowMap = this._windowMap;
        let imWindow: IimguiWindow;
        for (let key in windowMap) {
            imWindow = windowMap[key];
            imWindow.isShow && imWindow.loop();
        }
        im.EndFrame();
        im.Render();
        imgui_imp.RenderDrawData(im.GetDrawData());
    }
    destroy() {
        this.stopLoop();
        this.destroyImgui();
        this._isDestroy = true;
    }
    destroyImgui(): Promise<void> {
        const gl: WebGLRenderingContext | null = imgui_imp.gl;
        if (gl) {
            gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
            gl.clearColor(0, 0, 0, 0);
            gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
            gl.enable(gl.BLEND);
            gl.clear(gl.COLOR_BUFFER_BIT);
        }

        const ctx: CanvasRenderingContext2D | null = imgui_imp.ctx;
        if (ctx) {
            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        }

        // Cleanup
        imgui_imp.Shutdown();
        im.DestroyContext();

        console.log("Total allocated space (uordblks) @ _done:", im.bind.mallinfo().uordblks);
        return
    }
    async addFontFromFileTTF(url: string
        , size_pixels: number, font_cfg: im.ImFontConfig | null = null
        , glyph_ranges: number | null = null): Promise<im.ImFont> {
        font_cfg = font_cfg || new im.ImFontConfig();
        font_cfg.Name = font_cfg.Name || `${url.split(/[\\\/]/).pop()}, ${size_pixels.toFixed(0)}px`;
        const arrayBuffer = await this.loadArrayBuffer(url);
        return im.GetIO().Fonts.AddFontFromMemoryTTF(arrayBuffer, size_pixels, font_cfg, glyph_ranges);
    }
    async loadArrayBuffer(url: string): Promise<ArrayBuffer> {
        const response: Response = await fetch(url);
        return response.arrayBuffer();
    }
    loadImguiLib(onload: (isOk: boolean) => void) {}
}
